package com.fishery.processing.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fishery.entity.GlobalException;
import com.fishery.entity.StatusCode;
import com.fishery.processing.entity.Job;
import com.fishery.processing.entity.MaterialInventory;
import com.fishery.processing.entity.Product;
import com.fishery.processing.entity.ProductBatch;
import com.fishery.processing.entity.vo.JobVo;
import com.fishery.processing.mapper.JobMapper;
import com.fishery.processing.mapper.MaterialInventoryMapper;
import com.fishery.processing.mapper.ProductBatchMapper;
import com.fishery.processing.mapper.ProductMapper;
import com.fishery.processing.service.JobService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fishery.processing.util.ConvertUtil;
import com.fishery.processing.util.WrapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Wrapper;
import java.util.Date;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author run
 * @since 2021-03-12
 */
@Service
public class JobServiceImpl extends ServiceImpl<JobMapper, Job> implements JobService {

    @Autowired
    private JobMapper jobMapper;

    @Autowired
    private ConvertUtil convertUtil;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private MaterialInventoryMapper materialMapper;

    @Autowired
    private ProductBatchMapper batchMapper;

    @Override
    public IPage<JobVo> getJobsOfFactory(String factoryId, Integer page, Integer size) {
        IPage<Job> jobIPage = new Page<>(page, size);
        QueryWrapper<Job> wrapper = new QueryWrapper<>();
        wrapper.eq("processing_factory_id", factoryId);
        return convertUtil.convert(jobMapper.selectPage(jobIPage, wrapper), JobVo.class);
    }

    @Override
    @Transactional
    public boolean createJob(Job job) {
        if (productMapper.selectById(job.getProductId()) == null){
            throw new GlobalException(StatusCode.ERROR, "该加工产品不存在");
        }

        int materialResult = materialMapper.update(new MaterialInventory(), WrapperUtil.buildMaterialWrapper(job,false));

        if (materialResult < 1){
            throw new GlobalException(StatusCode.ERROR, "原料不存在或库存不足");
        }

        return jobMapper.insert(job) > 0;
    }

    @Override
    @Transactional
    public boolean updateJob(Job job) {
        Job oldJob = jobMapper.selectById(job.getId());
        if (oldJob == null){
            throw new GlobalException(StatusCode.ERROR, "不存在该加工作业");
        }

        if (oldJob.getMaterialId() != job.getMaterialId()){
            MaterialInventory inventory = new MaterialInventory();
            int oldResult = materialMapper.update(inventory, WrapperUtil.buildMaterialWrapper(oldJob, true));
            int newResult = materialMapper.update(inventory, WrapperUtil.buildMaterialWrapper(job, false));
            if (oldResult < 1 || newResult < 1){
                throw new GlobalException(StatusCode.ERROR, "修改原料库存失败");
            }
        }

        UpdateWrapper<Job> updateWrapper = new UpdateWrapper<>();

        int update;

        //如果加工作业未完成
        if (oldJob.getCompleteTime() == null){
            updateWrapper.eq("id", job.getId())
                            .set(!oldJob.getJobDescription().equals(job.getJobDescription())
                                        ,"job_description", job.getJobDescription())
                            .set(!oldJob.getProductWeight().equals(job.getProductWeight())
                                                    && job.getProductWeight() > 0
                                                    ,"product_weight"
                                                    , job.getProductWeight());

            if (!oldJob.getProductId().equals(job.getProductId())){
                Product product = productMapper.selectById(job.getProductId());
                if (product == null){
                    throw new GlobalException(StatusCode.ERROR, "修改的产品不存在");
                }
                updateWrapper.set("product_id", job.getProductId());
            }

            update = jobMapper.update(oldJob, updateWrapper);

        }else {
            updateWrapper.eq("id", job.getId())
                            .set(!oldJob.getJobDescription().equals(job.getJobDescription())
                                    , "job_description", job.getJobDescription());

            update = jobMapper.update(oldJob, updateWrapper);
        }

        return update > 0;
    }

    @Override
    @Transactional
    public boolean deleteJob(String jobId) {
        Job oldJob = jobMapper.selectById(jobId);

        int result;

        //如果加工作业未完成
        if (oldJob.getCompleteTime() == null){
            result = jobMapper.deleteById(jobId);

            //返还原料
            int update = materialMapper.update(new MaterialInventory(), WrapperUtil.buildMaterialWrapper(oldJob,true));
            if (update < 1){
                throw new GlobalException(StatusCode.ERROR,"返回原料失败");
            }
        }else {
            result = jobMapper.deleteById(jobId);
        }

        if (result < 1){
            throw new GlobalException(StatusCode.ERROR, "删除失败");
        }

        return true;
    }

    @Override
    @Transactional
    public boolean updateStatus(String jobId) {
        Job oldJob = jobMapper.selectById(jobId);
        if (oldJob == null){
            throw new GlobalException(StatusCode.ERROR, "不存在该加工作业");
        }

        if (oldJob.getCompleteTime() != null){
            throw new GlobalException(StatusCode.ERROR, "该加工作业已完成");
        }

        UpdateWrapper<Job> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", jobId)
                .set("complete_time", new Date());

        int result = jobMapper.update(oldJob, wrapper);

        if (result < 1){
            throw new GlobalException(StatusCode.ERROR, "修改失败");
        }

        int insert = batchMapper.insert(new ProductBatch(jobId
                                        , oldJob.getProductWeight()
                                        , oldJob.getProcessingFactoryId()));

        if (insert < 1){
            throw new GlobalException(StatusCode.ERROR, "产品批次生成失败");
        }

        return true;
    }

    @Override
    public JobVo getJobById(String jobId) {
        return jobMapper.getJobById(jobId);
    }
}
